//
//  YMMainPlayerView.m
//  SmartCar
//
//  Created by y s on 2022/12/20.
//

#import "YMMainPlayerView.h"
#import <AVFoundation/AVFoundation.h>
#import "YMPlayerSlider.h"

typedef void( ^STask)(BOOL);
@interface YMMainPlayerView()

/** 背景图 */
@property (nonatomic, strong) UIImageView *imgvBg;

@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerLayer *playerLayer;

@property (nonatomic,strong) YMPlayerSlider *slider;
@property (nonatomic,strong) UIProgressView *progressView;
/** 加载loading */
@property (nonatomic,strong) UIActivityIndicatorView *vActivity;

@property (nonatomic,strong) UILabel *currentTime;
@property (nonatomic,strong) UILabel *totalTime;
@property (nonatomic,strong) UIButton *fullButton;
/** 视频倍率 */
@property (nonatomic,strong) UIButton *btnRate;
@property (nonatomic, strong) SPlayerMultipleSheet *vRateSheet;

@property (nonatomic, strong) id playbackObserver;
@property (nonatomic, assign) BOOL isCheckedNetwork;

@property (nonatomic, assign) NSTimeInterval lastTime;
@property (nonatomic, assign) BOOL paused;


@property (nonatomic, strong) STask task;

@end

@implementation YMMainPlayerView

- (instancetype)init{
    self = [super init];
    if (self) {
        _autoHideToolbar = YES;
        [self setUI];
        [self layout];
        [self addNoti];
    }
    return self;
}
#pragma mark -- UI
- (void)setUI{
    [self addSubview:self.imgvBg];
    [self addSubview:self.vActivity];
    [self addSubview:self.topTitle];
    [self addSubview:self.toolView];
    [self addSubview:self.vRateBg];
    [self addSubview:self.playButton];
}

- (void)addNoti{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
}

- (void)layoutSubviews{
    [super layoutSubviews];
    _playerLayer.frame = self.bounds;
}
- (void)layout {
    [_imgvBg mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(0);
    }];
    [_topTitle mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo([SFitUtil fit:15]);
        make.right.mas_equalTo(-[SFitUtil fit:15]);
        make.top.mas_equalTo([SFitUtil fit:12]);
    }];
    [_toolView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.bottom.mas_equalTo(0);
        make.height.mas_equalTo([SFitUtil fit:40]);
    }];
    [_vActivity mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(0);
    }];
    [_playButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo([SFitUtil fit:55]);
        make.height.mas_equalTo([SFitUtil fit:55]);
        make.center.equalTo(self);
    }];
    [_currentTime mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(10);
        make.width.mas_equalTo(50);
        make.centerY.mas_equalTo(0);
    }];
    [_totalTime mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo(self.btnRate.mas_left);
        make.width.mas_equalTo(50);
        make.centerY.mas_equalTo(0);
    }];
    [_progressView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(_currentTime.mas_right).offset(10);
        make.right.mas_equalTo(_totalTime.mas_left).offset(-10);
        make.centerY.mas_equalTo(0);
        make.height.mas_equalTo(4);
    }];
    [_slider mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.mas_equalTo(0).offset(-1);
        make.left.mas_equalTo(_progressView).offset(-1);
        make.right.mas_equalTo(_progressView);
        make.height.mas_equalTo(10);
    }];
    [self.btnRate mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.fullButton.mas_left);
        make.top.bottom.mas_equalTo(0);
        make.width.mas_equalTo(0);
    }];
    [_fullButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.bottom.mas_equalTo(0);
        make.right.mas_equalTo(-[SFitUtil fit:10]);
        make.width.mas_equalTo([SFitUtil fit:40]);
    }];
    [self.vRateBg mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo([SFitUtil fit:-50]);
        make.bottom.equalTo(self.toolView.mas_top);
        make.size.mas_equalTo([SPlayerMultipleSheet getViewSize:NO]);
    }];
}

#pragma mark -- public methods
- (void)playWithUrlString:(NSString *)urlString
{
    if(urlString.length<1){
        //非法播放地址...
        [self stop];
        return;
    }
    if([_urlString isEqualToString:urlString]){
        //播放地址重复...
        return;
    }
    _urlString = urlString;
    [self restart];
    if (_player.currentItem) {
        [self playerItemRemoveNotification];
        [self playerItemRemoveObserver];
    }
    [_player replaceCurrentItemWithPlayerItem:nil];
    AVPlayerItem *playerItem = [self getPlayerItemWithURLString:urlString];
    [self addObserverToPlayerItem:playerItem];
    [_player replaceCurrentItemWithPlayerItem:playerItem];
    self.lastTime = 0.0;
    [self playerItemAddNotification];
}
- (void)restart{
    _playEnded = NO;
    _paused = NO;
    [self pause];
    if (_playButton.selected) {
        _playButton.selected = NO;
    }
    _playButton.hidden = YES;
    [_vActivity startAnimating];
}
- (void)play{
    //开始回放视频
    if(_urlString.length<1){
        return;
    }
    if ([self isPlaying]) {
        return;
    }
    if (_playEnded == YES) {
        [_player seekToTime:CMTimeMakeWithSeconds(0, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
        _playEnded = NO;
    }
    _playButton.selected=YES;
    [_player play];
    if(_delegate && [_delegate respondsToSelector:@selector(playStart)]){
        [_delegate playStart];
    }
}
- (void)pause{
    //暂停回放视频
    if(_urlString.length<1){
        return;
    }
    if (![self isPlaying]) {
        return;
    }
    _playButton.selected=NO;
    [_player pause];
    if(_delegate && [_delegate respondsToSelector:@selector(playPause)]){
        [_delegate playPause];
    }
}
- (void)stop{
    [_vActivity stopAnimating];
    _playButton.hidden = YES;
    _toolView.hidden = YES;
    _topTitle.hidden = YES;
    _urlString=nil;
    _playEnded=NO;
    _paused =NO;
    if(_player){
        if(_playbackObserver && _urlString != nil && _urlString.length > 0){
            [_player removeTimeObserver:_playbackObserver];
        }
        [self playerItemRemoveObserver];
        [_player replaceCurrentItemWithPlayerItem:nil];
    }
    if(_delegate && [_delegate respondsToSelector:@selector(playStop)]){
        [_delegate playStop];
    }
}
- (BOOL)isPlaying{
    if([[UIDevice currentDevice] systemVersion].intValue >= 10){
        return _player.timeControlStatus == AVPlayerTimeControlStatusPlaying;
    }else{
        return _player.rate == 1;
    }
    return YES;
}


- (void)autoHideToolBar{
    if(_task){
        [STimeUtil cancel:_task];
        _task=nil;
    }
    __weak typeof(self) weakSelf=self;
    _task = [STimeUtil delay:3 task:^{
        [weakSelf hidePlayBtn];
        //如果是自动隐藏，就隐藏toobar
        if(weakSelf.autoHideToolbar == YES)
            [weakSelf hideToolBar];
    }];
}

- (void)showToolBar{
    _topTitle.hidden=NO;
    _toolView.hidden=NO;
    _playButton.hidden = NO;
    if(_delegate &&  [_delegate respondsToSelector:@selector(toolBarChangeHidden)]){
        [_delegate toolBarChangeHidden];
    }
    [self autoHideToolBar];
}

- (void)hideToolBar{
    if (_vRateBg.isHidden == false){
        return;
    }
    _topTitle.hidden = YES;
    _toolView.hidden = YES;
    if(_delegate && [_delegate respondsToSelector:@selector(toolBarChangeHidden)]){
        [_delegate toolBarChangeHidden];
    }
    if(_task){
        [STimeUtil cancel:_task];
        _task=nil;
    }
}

- (void)hidePlayBtn
{
    _playButton.hidden = YES;
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSString *,id> *)change
                       context:(void *)context{
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerStatus status= [[change objectForKey:@"new"] intValue];
        if (status == AVPlayerStatusReadyToPlay) {
            [_vActivity stopAnimating];
            [self resetTimeLabel];
            _playButton.enabled = YES;
            _slider.enabled = YES;
            if(!_isCheckedNetwork){
                _isCheckedNetwork = YES;
                [self play];
            }else{
                [self play];
            }
        }else{
            // 暂停
            NSLog(@"播放器状态 %ld",(long)status);
            [self pause];
        }
    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        NSArray *array = _player.currentItem.loadedTimeRanges;
        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围
        NSTimeInterval startSeconds = CMTimeGetSeconds(timeRange.start);//本次缓冲起始时间
        NSTimeInterval durationSeconds = CMTimeGetSeconds(timeRange.duration);//缓冲时间
        NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度
        
        NSTimeInterval currentTime = CMTimeGetSeconds(self.player.currentTime);
        NSLog(@"当前播放的位置: %f 当前缓冲的开始时间: %f 范围: %f",currentTime,startSeconds,durationSeconds);
        
        if ((currentTime > self.lastTime) && (currentTime > startSeconds)) {
            NSLog(@"开始播放了,,,");
            [self.vActivity stopAnimating];
            self.vActivity.hidesWhenStopped = YES;
        }else{
            NSLog(@"停止播放了...");
            [self.vRateSheet hide];
        }
        
        self.lastTime = currentTime;
        
        float totalTime = CMTimeGetSeconds(_player.currentItem.duration);//视频总长度
        float progress = totalBuffer/totalTime;//缓冲进度
        [_progressView setProgress:progress];
    }
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    if(_urlString.length<1){
        return;
    }
    UITouch *touch = [touches anyObject];
    if (touch.view == _toolView){
        return;
    }
    if(_notCanTouch == YES){
        return;
    }
    if(_autoHideToolbar)
    {
        if(_toolView.hidden){
            [self showToolBar];
        }else{
            [self hidePlayBtn];
            [self hideToolBar];
        }
    }else
    {
        if(_playButton.hidden){
            [self showToolBar];
        }else{
            [self hidePlayBtn];
        }
    }
}
#pragma mark - 私有方法
- (AVPlayerItem *)getPlayerItemWithURLString:(NSString *)path {
    NSURL *url = [NSURL URLWithString:[SDataUtil encodeURLQuery:path]];
    AVPlayerItem *item = [AVPlayerItem playerItemWithURL:url];
    return item;
}

#pragma mark -- 观察者
- (void)playerItemAddNotification {
    //添加 通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];

}
- (void)addObserverToPlayerItem:(AVPlayerItem *)playerItem {
    //添加 KVO
    if(playerItem){
        [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
        [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
        NSLog(@"add kvo");
    }
}
- (void)playerItemRemoveNotification{
    //移除通知..
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
}
- (void)playerItemRemoveObserver{
    //移除 KVO
    if(_player.currentItem!=nil){
        [_player.currentItem removeObserver:self forKeyPath:@"status"];
        [_player.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
        NSLog(@"remove kvo");
    }
}
// 播放结束
- (void)playbackFinished:(NSNotification *)noti{
    _playEnded = YES;
    _playButton.selected = NO;
    _slider.value = 1.0;
    // 播放结束样式处理
    if(_delegate!=nil && [_delegate performSelector:@selector(playFinished)]){
        [_delegate playFinished];
    }
}

- (void)applicationWillResignActive:(NSNotification *)noti{
    if(self.playEnded)return;

    if ([self isPlaying]) {
        [self clickPlay:_playButton];
    }
}

- (void)applicationDidBecomActive:(NSNotification *)noti{
    if(self.playEnded){
        return;
    }
    if ([self isPlaying]) {
        [self clickPlay:_playButton];
    }
}
#pragma mark - 点击/滑动动作
- (void)clickPlay:(UIButton *)sender{
    if (![self isPlaying]) {
        sender.selected = YES;
        _paused = NO;
        [self play];
    } else if ([self isPlaying]) {
        sender.selected = NO;
        _paused = YES;
        [self pause];
    }
}

- (void)sliderTouchBegin:(UISlider *)sender{
    [self pause];
}
- (void)sliderValueChanged:(UISlider *)sender{
    NSTimeInterval currentTime = CMTimeGetSeconds(self.player.currentItem.duration) * self.slider.value;
    NSInteger currentMin = currentTime / 60;
    NSInteger currentSec = (NSInteger)currentTime % 60;
    self.currentTime.text = [NSString stringWithFormat:@"%02td:%02td",currentMin,currentSec];
}
- (void)sliderTouchEnd:(UISlider *)sender{
    NSTimeInterval slideTime = CMTimeGetSeconds(_player.currentItem.duration) * self.slider.value;
    if (slideTime == CMTimeGetSeconds(_player.currentItem.duration)) {
        slideTime -= 0.5;
    }
    [_player seekToTime:CMTimeMakeWithSeconds(slideTime, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
    if (_paused==NO && _playEnded==NO) {
        [self play];
    }
}

- (void)clickFullScreen:(UIButton *)sender
{
    _fullScreen = !_fullScreen;
    [self resetAll:NO];
    [self showToolBar];
    if(_delegate!=nil && [_delegate respondsToSelector:@selector(clickPlayerFullScreen:)]){
        [_delegate clickPlayerFullScreen:self];
    }
}
- (void)rateClickAction:(UIButton *)sender{
    self.vRateBg.hidden = NO;
    [self.vRateSheet show:self.vRateBg isFull:_fullScreen];
}
- (void)resetAll:(BOOL)isFullBack{
    if (isFullBack){
        _fullScreen = NO;
    }
    self.fullButton.selected = _fullScreen;
    [self.vRateSheet hide];
    [self.vRateSheet resetDeafultStatus];
    self.btnRate.hidden = !_fullScreen;
    [self.btnRate mas_updateConstraints:^(MASConstraintMaker *make) {
        if (self.fullScreen){
            make.width.mas_equalTo([SFitUtil fit:56]);
        }else{
            make.width.mas_equalTo(0);
        }
    }];
}

#pragma mark - Time Label
- (void)resetTimeLabel {
    NSTimeInterval totalTime = CMTimeGetSeconds(self.player.currentItem.duration);
    NSTimeInterval currentTime = CMTimeGetSeconds(self.player.currentTime);
    // 切换视频源时totalTime/currentTime的值会出现nan导致时间错乱
    if (!(totalTime>=0)||!(currentTime>=0)) {
        totalTime = 0;
        currentTime = 0;
    }
    NSInteger totalMin = totalTime / 60;
    NSInteger totalSec = (NSInteger)totalTime % 60;
    self.totalTime.text = [NSString stringWithFormat:@"%02td:%02td",totalMin,totalSec];
    
    NSInteger currentMin = currentTime / 60;
    NSInteger currentSec = (NSInteger)currentTime % 60;
    self.currentTime.text = [NSString stringWithFormat:@"%02td:%02td",currentMin,currentSec];
}

#pragma mark -- getter
- (UIImageView *)imgvBg{
    if(_imgvBg == nil){
        _imgvBg = [[UIImageView alloc]init];
        _imgvBg.backgroundColor = [UIColor blackColor];
        _imgvBg.contentMode = UIViewContentModeScaleAspectFit;
        [_imgvBg.layer addSublayer:self.playerLayer];
    }
    return _imgvBg;
}
- (UILabel *)topTitle{
    if (!_topTitle) {
        _topTitle = [SThemeUtil boldLabel:@"" color:STheme.H_D9 fontSize:16];
        _topTitle.hidden=true;
        _topTitle.numberOfLines=0;
    }
    return _topTitle;
}
- (UIView *)toolView {
    if(_toolView==nil){
        _toolView=[[UIView alloc] init];
        _toolView.hidden = YES;
        UIImageView *imgvBg = [[UIImageView alloc] init];
        imgvBg.image = [UIImage imageNamed:@"player_toolbar_bg_icon"];
        [_toolView addSubview:imgvBg];
        [_toolView addSubview:self.currentTime];
        [_toolView addSubview:self.progressView];
        [_toolView addSubview:self.slider];
        [_toolView addSubview:self.totalTime];
        [_toolView addSubview:self.btnRate];
        [_toolView addSubview:self.fullButton];
        [imgvBg mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.mas_equalTo(0);
        }];
    }
    return _toolView;
}
- (UIButton *)playButton{
    if(_playButton==nil){
        _playButton=[UIButton buttonWithType:UIButtonTypeCustom];
        [_playButton setImage:[UIImage imageNamed:@"video_play_icon"] forState:UIControlStateNormal];
        [_playButton setImage:[UIImage imageNamed:@"video_suspend_icon"] forState:UIControlStateSelected];
        [_playButton addTarget:self action:@selector(clickPlay:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _playButton;
}
- (UIButton *)fullButton {
    if(_fullButton==nil){
        _fullButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_fullButton setImage:[UIImage imageNamed:@"player_full_screen"] forState:UIControlStateNormal];
        [_fullButton setImage:[UIImage imageNamed:@"player_small_screen"] forState:UIControlStateSelected];
        __weak typeof(self) weakSelf=self;
        [_fullButton g_clickBlock:^(id sender) {
            [weakSelf clickFullScreen:sender];
        }];
    }
    return _fullButton;
}
- (UIButton *)btnRate {
    if(_btnRate == nil){
        _btnRate = [UIButton buttonWithType:UIButtonTypeCustom];
        [_btnRate setTitle:@"倍速" forState:UIControlStateNormal];
        [_btnRate setTitleColor:STheme.D9 forState:UIControlStateNormal];
        _btnRate.titleLabel.font = [SFitUtil fitBoldFont:14];
        _btnRate.hidden = YES;
        [_btnRate addTarget:self action:@selector(rateClickAction:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _btnRate;
}
- (UILabel *)currentTime{
    if(_currentTime == nil){
        _currentTime = [[UILabel alloc] init];
        _currentTime.font = [SFitUtil fitFont:12];
        _currentTime.textColor = [UIColor whiteColor];
        _currentTime.textAlignment = NSTextAlignmentCenter;
    }
    return _currentTime;
}
- (UILabel *)totalTime{
    if(_totalTime == nil){
        _totalTime = [[UILabel alloc] init];
        _totalTime.font = [SFitUtil fitFont:12];
        _totalTime.textColor = [UIColor whiteColor];
        _totalTime.textAlignment=NSTextAlignmentCenter;
    }
    return _totalTime;
}
- (UIProgressView *)progressView{
    if(_progressView == nil){
        _progressView=[[UIProgressView alloc] init];
        _progressView.progressViewStyle = UIProgressViewStyleDefault;
        [_progressView setProgressTintColor:[SUIUtil colorOf:0x808080]];
        [_progressView setTrackTintColor:[SUIUtil colorOf:0xffffff alpha:0.15]];
    }
    return _progressView;
}
- (YMPlayerSlider *)slider{
    if(_slider == nil) {
        _slider = [[YMPlayerSlider alloc] init];
        [_slider setThumbImage:[UIImage imageNamed:@"player_slider_point"] forState:UIControlStateNormal];
        [_slider setMaximumTrackImage:[UIImage imageWithColor:[UIColor clearColor] size:CGSizeMake(300, 2)] forState:UIControlStateNormal];
        [_slider addTarget:self action:@selector(sliderTouchBegin:) forControlEvents:UIControlEventTouchDown];
        [_slider addTarget:self action:@selector(sliderTouchEnd:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
        [_slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
        _slider.enabled = YES;
        _slider.minimumTrackTintColor = STheme.D12;
    }
    return _slider;
}
- (AVPlayerLayer *)playerLayer{
    if (!_playerLayer) {
        _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    }
    return _playerLayer;
}
- (AVPlayer *)player{
    if (_player == nil){
        _player = [[AVPlayer alloc] init];
        _player.automaticallyWaitsToMinimizeStalling = NO;
        __weak typeof(self) weakSelf=self;
        _playbackObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) {
            [weakSelf resetTimeLabel];
            NSTimeInterval totalTime = CMTimeGetSeconds(weakSelf.player.currentItem.duration);
            //time.value/time.timescale是当前时间
            weakSelf.slider.value = time.value/time.timescale/totalTime;
        }];
    }
    return _player;
}

- (UIActivityIndicatorView *)vActivity{
    if(_vActivity == nil){
        _vActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:
                       UIActivityIndicatorViewStyleWhiteLarge];
    }
    return _vActivity;
}

- (UIView *)vRateBg{
    if (_vRateBg == nil){
        _vRateBg = [[UIView alloc] init];
        _vRateBg.hidden = YES;
        _vRateBg.clipsToBounds = YES;
        [_vRateBg addSubview:self.vRateSheet];
    }
    return _vRateBg;
}
- (SPlayerMultipleSheet *)vRateSheet{
    if (_vRateSheet == nil) {
        _vRateSheet = [[SPlayerMultipleSheet alloc] init];
        WEAK_SELF;
        _vRateSheet.changeMulpleBlock = ^(float rate){
            weakSelf.player.rate = rate;
        };
    }
    return _vRateSheet;
}

- (void)dealloc{
    if(_task){
        [STimeUtil cancel:_task];
        _task=nil;
    }
    [self stop];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


@end
